//
// Created by 17328 on 2025/8/18.
//
#include "AgcReturn.h"
#include <cstdio>

#include "Agc.h"

// 1. 静态成员变量 只允许在某个 .cpp 文件里定义一次;
// 2. .h 文件里只声明，不要初始化;
// 3. 多个 .cpp 文件包含同一个 .h 文件不会重复定义，因为它只是声明，不分配内存;
// 4. 如果你在多个 .cpp 文件都写了这行，链接器会报 multiple definition 或 重复符号 错误;
// 5. 私有变量其他 .cpp 文件里的普通函数 / main() 无法访问，只能类的成员函数访问;
AgcReturn* AgcReturn::Instance = new AgcReturn();

AgcReturn::~AgcReturn() {
    if (AgcReturnParameters != nullptr) {
        // delete 与 new 搭配使用，delete 释放内存，new 申请内存。
        // malloc 与 free 搭配使用，malloc 申请内存，free 释放内存。malloc是硬地址申请，不会调用构造函数。
        delete[] AgcReturnParameters;
        // 防止指针悬空
        AgcReturnParameters = nullptr;
    }
}

void AgcReturn::SetTime(long time) {
    this->time = time;
}

void AgcReturn::SetAgcValue(float value) {
    this->AgcValue = value;
}

void AgcReturn::SetFrmCapacity(float capacity) {
    DEBUG("SetFrmCapacity: %f", capacity);
    this->FrmCapacity = capacity;
}

long AgcReturn::GetTime() {
    return this->time;
}

float AgcReturn::GetAgcValue() {
    return this->AgcValue;
}

float AgcReturn::GetFrmCapacity() {
    return this->FrmCapacity;
}

// in[]：【装机容量, 数组长度, 数组长度的参数】
void AgcReturn::SetAgcReturnParameters(float in[]) {
    // 1. 设置装机容量
    // FrmCapacity是一个普通的float类型成员变量，存储在对象的内存中（栈或堆上，取决于对象的创建方式）
    // 简单的赋值操作（如FrmCapacity = capacity）不会涉及动态内存分配，因此不会导致内存泄漏
    // 内存泄漏通常发生在使用new、malloc等函数分配内存后，忘记使用delete、free释放内存的情况
    this->SetFrmCapacity(in[0]);
    // 2. 设置数组长度
    // AgcReturnParameters指针本身作为AgcReturn类成员变量，存储在堆上（因为 AgcReturn 对象是通过 new 创建的）。
    // 通过 new 分配的 float[(int)in[1]] 数组内存存储在堆上。
    // AgcReturnParameters 是 AgcReturn 类的一个成员变量，类型为 float*。由于 AgcReturn 使用了单例模式，整个程序中只会有一个 AgcReturn 实例，因此 AgcReturnParameters 指针也只会有一份。
    // 但是，每次调用 SetAgcReturnParameters 方法时，都会重新分配内存 (new float[(int)in[1]])，但之前的内存没有被释放，这就导致了内存泄漏。
    if (AgcReturnParameters != nullptr) {
        // 每次new数组前，释放之前申请的内存，避免内存泄漏
        delete[] AgcReturnParameters;
        // 避免AgcReturnParameters成为悬空指针，delete[] 后，如果不置空，指针仍然指向那块已经释放的内存 → 悬空指针。
        AgcReturnParameters = nullptr;
    }
    AgcReturnParameters = new float[(int)in[1]];
    // 3. 设置初始化参数
    for (int i = 0; i < in[1]; i++) {
        AgcReturnParameters[i] = in[i + 2];
    }
}

// 实现单例模式，应该声明为一个 静态函数，返回唯一实例
// 单例模式的饿汉式
AgcReturn* AgcReturn::getInstance() {
    return Instance;
}